# -*- coding: utf-8 -*-

"""
  @author: tangliqi
  @date: 2022/11/28 15:40
  @python version: 3.6 
  @contact me: 110
  ---------------------------------------
  @desc: python设计模式实现 => 享元模式.py
"""


# 通过一个象棋的例子来说明享元模式。
# 象棋游戏中，有非常多的棋局，每个棋局中，用到的棋子都是一样的，只是坐标不一样。
# 如果每个棋局都创建自己的棋子对象，则有大量重复的对象被创建出来。
# 可以把这些棋子对象抽象出来复用，每个棋局不一样的只是具体棋子的坐标,还有所属的棋局。
# 我们拿其中的帅和兵列举，其它是同理。

# ============================  抽象共享类  ============================
# 要被共享的类就是这些基本的棋子类
class Chess:
    pass


class Jiang(Chess):
    def __init__(self):
        self.text = "将"

    def __str__(self):
        return "这是一个将"


class Soldier(Chess):
    def __init__(self):
        self.text = "兵"

    def __str__(self):
        return "这是一个兵"


# ============================  享元工厂类  ============================
# 通过一个享元工厂来缓存所有的基本棋子对象，工厂类获取到的就是享元。
# 这样就从每个棋局维护三十个多个基本棋子对象，变成了全局维护三十多个基本棋子对象，节省了大量内存。

class FlyWeightFactory:

    def __init__(self):
        self.chess_map = {
            "jiang": Jiang(),
            "soldier": Soldier()
        }

    def get_chess(self, chess_name):
        assert chess_name in self.chess_map, "工厂中不存在该名字的类"
        return self.chess_map[chess_name]


# ============================  具体棋盘中的棋子类  ============================
class ChessPiece:
    def __init__(self, chessboard_id, chess: Chess, color):
        self.x = 0
        self.y = 0
        self.chessboard_id = chessboard_id
        self.color = color
        self.chess = chess

    def get_chess_info(self):
        info = f"chessboard_id:{self.chessboard_id};{self.chess} with {self.color} in {self.x}/{self.y}"
        return info


if __name__ == '__main__':
    # 享元工厂
    fac = FlyWeightFactory()

    # 创建一个id为1的棋盘中具体应用的红色小兵
    chessboard_id = 1
    red_soldier = ChessPiece(chessboard_id, fac.get_chess("soldier"), "red")
    print(red_soldier.get_chess_info())
